from flask import Flask,request
from git.repo import Repo
import shutil
import threading
import os
import sys
import json
import time
import testPort

ganacheCli_START_PORT = 1000
http_START_PORT = 4000

app = Flask(__name__)

homePath = os.path.expanduser('~')
projectPath = os.path.join(homePath, ".edtp/project/")

host_ip = testPort.get_host_ip()

# @app.route("/", methods=["GET", "POST"])
# def hello():
#     #request.url_root()
#     return "hello world"

def threading_CloneStart(git, path, branch):
    repo = Repo.clone_from(git, path)
    #切换分支不确定
    repo.heads[branch].checkout()
    return repo

def threading_RunganacheCli(newPort, newDBPath):
    os.system('sudo ' + "ganache-cli \
            -p %s \
            -h 0.0.0.0 \
            -i 1000 \
            --db %s \
            --gasLimit=8000000 \
            --callGasLimit=8000000 \
            --account=0x9a28e3c832827b79e856b1868289ad99dbdab3f8cf4e7e9d1932069afe9e0fd3,10000000000000000000000000 \
            --account=0xcfa14af5efed674e70b773f9365f4e9ce782bada80fded7ef210f6236c5897d9,10000000000000000000000000 \
            --account=0xa2f267bc2f0e8ee74084a2e3b471cc95f85c5282d79e8279f8cb5ee61353ba2b,10000000000000000000000000 \
            --account=0x80abf11467743ba92b48048fc82ffc938de861c42a5d56eca16ecd213ab01900,10000000000000000000000000 \
            --account=0x4b45f01558c94c78343aa9f43ffe2bc2f3e8862ab45dfaddaa2e9ff657a5071a,10000000000000000000000000 \
            --account=0x4bd8037083760474e0be92391cd5199d317c45e9ef6ef6999c824dab85bee61e,10000000000000000000000000 \
            --account=0xe7eb82cf2d18c193b9da8756b9e798f7606f55d25eec8c3b511f9e968d01880d,10000000000000000000000000 \
            --account=0x7b4bc7e4a5cd54ebbc0b899e09f9fe37f48c5a7e7e3434b1e55cdc6507148864,10000000000000000000000000 \
            --account=0xc0826a3dd4c512beca30b6fc9ca31bb2f05dfd2c1d9e480da90dba57abd69500,10000000000000000000000000 \
            --account=0x3b354ad233208b69d640dff05b78cf8bd6bed489ec3ea1ea813f609cadcff036,10000000000000000000000000 \
            --account=0x86d6d9dabd953016d3a5444e209c58f19b0ddf3ab5e140494d991458ce4fa6f2,10000000000000000000000000 \
            --account=0x5d8e7f3b60419e270fcd104b269dfe96c6f25c7ecf521dddf3bba4c782ca01b7,10000000000000000000000000 \
            --account=0x644209e963b0ed98d49058c176a632fc739cb94349d2b8fb179227b85a6b29e4,10000000000000000000000000 \
            --account=0xb684ffe52a5372f71c203ecda6509d632f2a8f739d49786ed07449bf99f8b5f1,10000000000000000000000000 \
            --account=0xb33869f092cd18bb524a207c5afd39a5a5bc1187d95a484227b9eacdfb1a9f21,10000000000000000000000000" % (newPort, newDBPath))

def scanPort(START_PORT):
    resu = -1
    while testPort.is_port_used(host_ip, resu+START_PORT+1):
        resu += 1
    return resu+START_PORT+1

def findPort(nums, START_PORT):
    resuPort = START_PORT
    while resuPort < 65535:
        if resuPort not in nums:
            resuPort = scanPort(resuPort)
            if resuPort not in nums:
                return resuPort
        resuPort += 1
    else:
        return -1

@app.route('/project/add/<name>')
def project_add(name=None):
    git = request.values.get("git")
    branch = request.values.get("branch","master")
    if git :
        if not os.path.exists(projectPath + name):
            # repo = Repo.clone_from(git, projectPath + name)
            # #切换分支不确定
            # repo.heads[branch].checkout()  
            threading._start_new_thread(threading_CloneStart, (git, projectPath + name, branch, ))      
            resu = {"code":0, "result":{
                "name":name,
                "remoteURL":git[:-4],
                "webHookURL":request.url_root + "project/webhook/%s"%name, 
                "state":"clone start"
            }}
        else:
            resu = {"code":-1, "result":{}, "message":"project is already exist"}
    else: 
        resu = {"code":-1, "result":{}, "message":"no git"}
    return json.dumps(resu,ensure_ascii=False)

@app.route('/project/list')
def project_list():
    dirs = os.listdir(projectPath)
    result = []
    for p in dirs:
        result.append({"name":p, "remoteURL":Repo(projectPath + p).remote().url[:-4], "webHookURL":request.url_root + "project/webhook/%s"%p})
    resu = {"code":0, "result":result}
    return json.dumps(resu,ensure_ascii=False)

@app.route('/project/remove/<name>')
def project_remove(name="None"):
    if os.path.exists(projectPath + name):
        shutil.rmtree(projectPath + name)
        #os.system('sudo rm -rf .edtp/project/%s'%name)
        resu = {"code":0, "result":"remove project success"}
    else:
        resu = {"code":-2, "result":"remove project faild", "message":"project is not exist"}
    return json.dumps(resu,ensure_ascii=False)

@app.route('/project/webhook/<name>')
def project_webhook(name="None"):
    Repo(projectPath + name).remote().pull()


#ganache模块
@app.route('/ganache/list')
def ganache_list():
    with open(projectPath + '../ganacheServer.json','r') as fb:
        cases = json.load(fb)
    resu = {"code":0, "result":cases}
    return json.dumps(resu,ensure_ascii=False)

@app.route('/ganache/add/<name>')
def ganache_add(name):
    #fb = open("~/.edtp/ganacheServer.json") 读出
    #dicts = json.load(fb) 
    #fb = open('/home/satone/.edtp/ganacheServer.json','w') 写入
    #fb.write(json.dumps(dicts, indent=2)) 缩进2格
    with open(projectPath + '../ganacheServer.json','r') as fb:
        cases = json.load(fb)
    portList = []
    for every in cases:
        if name == every["name"]:
            resu = {"code":-3, "result":{}, "message":"name already exists"}
            return json.dumps(resu,ensure_ascii=False)
        portList.append(int(every['port']))
    newPort = str(findPort(portList, ganacheCli_START_PORT))
    #newPort = str(scanPort(ganacheCli_START_PORT))
    newDBPath = projectPath + '../ganache/%s/db' % name
    if not os.path.exists(newDBPath): 
        os.makedirs(newDBPath)
    threading._start_new_thread(threading_RunganacheCli, (newPort, newDBPath, ))
    newCase = {"name":name, "port":newPort, "createTime":str(int(time.time())), "state":"running"}
    cases.append(newCase)
    resu = {"code":0, "result":newCase}
    with open(projectPath + '../ganacheServer.json','w') as fb:
        fb.write(json.dumps(cases, indent=2))
    return json.dumps(resu,ensure_ascii=False)

@app.route('/ganache/remove/<name>')
def ganache_remove(name):
    usePort = None
    with open(projectPath + '../ganacheServer.json','r') as fb:
        cases = json.load(fb)
    for every in cases:
        if every['name'] == name:
            usePort = every['port']
            cases = cases[:cases.index(every)] + cases[cases.index(every)+1:]
    if usePort:
        os.system('''kill -9 $(netstat -nlp | grep :''' + usePort + ''' | awk '{print $7}' | awk -F"/" '{ print $1 }')''')
        shutil.rmtree(projectPath + '../ganache/%s' % name)
        with open(projectPath + '../ganacheServer.json','w') as fb:
            fb.write(json.dumps(cases, indent=2))
        resu = {"code":0, "result":"stop and remove success"}
    else:
        resu = {"code":-4, "message":"There is no ganache-cli named %s" % name}
    return json.dumps(resu,ensure_ascii=False)
    
@app.route('/ganache/restart/<name>')
def ganache_restart(name):
    usePort = None
    with open(projectPath + '../ganacheServer.json','r') as fb:
        cases = json.load(fb)
    for every in cases:
        if every['name'] == name:
            usePort = every['port']
            cases[cases.index(every)]['state'] = "running"
    if usePort:
        os.system('''kill -9 $(netstat -nlp | grep :''' + usePort + ''' | awk '{print $7}' | awk -F"/" '{ print $1 }')''')
        threading._start_new_thread(threading_RunganacheCli, (usePort, projectPath + '../ganache/%s/db' % name))
        with open(projectPath + '../ganacheServer.json','w') as fb:
            fb.write(json.dumps(cases, indent=2))
        resu = {"code":0, "result":"restart success"}
    else:
        resu = {"code":-4, "message":"There is no ganache-cli named %s" % name}
    return json.dumps(resu,ensure_ascii=False)

@app.route('/ganache/reset/<name>')
def ganache_reset(name):
    usePort = None
    with open(projectPath + '../ganacheServer.json','r') as fb:
        cases = json.load(fb)
    for every in cases:
        if every['name'] == name:
            usePort = every['port']
            cases[cases.index(every)]['state'] = "running"
    if usePort:
        os.system('''kill -9 $(netstat -nlp | grep :''' + usePort + ''' | awk '{print $7}' | awk -F"/" '{ print $1 }')''')
        shutil.rmtree(projectPath + '../ganache/%s/db' % name)
        os.makedirs(projectPath + '../ganache/%s/db' % name)
        threading._start_new_thread(threading_RunganacheCli, (usePort, projectPath + '../ganache/%s/db' % name))
        with open(projectPath + '../ganacheServer.json','w') as fb:
            fb.write(json.dumps(cases, indent=2))
        resu = {"code":0, "result":"reset success"}
    else:
        resu = {"code":-4, "message":"There is no ganache-cli named %s" % name}
    return json.dumps(resu,ensure_ascii=False)

@app.route('/ganache/poweroff/<name>')
def ganache_poweroff(name):
    usePort = None
    with open(projectPath + '../ganacheServer.json','r') as fb:
        cases = json.load(fb)
    for every in cases:
        if every['name'] == name:
            usePort = every['port']
            cases[cases.index(every)]['state'] = "poweroff"
    if usePort:
        os.system('''kill -9 $(netstat -nlp | grep :''' + usePort + ''' | awk '{print $7}' | awk -F"/" '{ print $1 }')''')
        with open(projectPath + '../ganacheServer.json','w') as fb:
            fb.write(json.dumps(cases, indent=2))
        resu = {"code":0, "result":"poweroff success"}
    else:
        resu = {"code":-4, "message":"There is no ganache-cli named %s" % name}
    return json.dumps(resu,ensure_ascii=False)

@app.route('/migrate/<name>?hport=<hport>&gport=<gport>&mpath=<mpath>')
def migrate_start(name):
    if not os.path.exists(projectPath + name + '/edtp/migrate.sh'):
        resu = {"code":-5, "result":"%s/edpt/migrate.sh not exists" % name}
        return json.dumps(resu,ensure_ascii=False)
    hport = request.values.get("hport")
    gport = request.values.get("gport")
    mpath = request.values.get("mpath")
    os.system(projectPath + name + '/edtp/migrate.sh ' + hport + ' ' + gport + ' ' + mpath)
    resu = {"code":0, "result":"migrate success"}
    return json.dumps(resu,ensure_ascii=False)

@app.route('/migrate/list/<projectname>/<ganachename>')
def migrate_list_project_ganache(projectname, ganachename):
    if not projectname:
        return "show all issue"
    else: 
        if not ganachename:
            return "show %s's all issue" % projectname
        else:
            return "show %s's %s issue" % (projectname, ganachename)

@app.route('/migrate/list/<projectname>')
def migrate_list_project(projectname):
    return migrate_list_project_ganache(projectname, None)

@app.route('/migrate/list')
def migrate_list():
    return migrate_list_project_ganache(None, None)


def ganache_init():
    newJson = []
    if os.path.exists(projectPath + '../ganache/'):
        casasDir = os.listdir(projectPath + '../ganache/')
    else:
        casasDir = []
    with open(projectPath + '../ganacheServer.json','r') as fb:
        cases = json.load(fb)
    for every in cases:
        if every['name'] in casasDir:
            every['state'] = "poweroff"
            newJson.append(every)
    with open(projectPath + '../ganacheServer.json','w') as fb:
        fb.write(json.dumps(newJson, indent=2))

if __name__ == "__main__":
    ganache_init()
    app.run(host="0.0.0.0", port=int(sys.argv[1]))
